package fr.compil.tab.model;

import java.util.Stack;
import java.util.regex.Pattern;

import javax.management.InvalidAttributeValueException;

import fr.compil.tab.logic.CellManager;

public class Token {
	private TokenType tokenType;
	private String value;
	private Board board;

	/*
	 * Returns the precedence of the operator. The higher the precedence, the
	 * faster you should process it. If the token is not an operator, returns
	 * -1.
	 */
	public Integer getPrecedence() {
		if(tokenType == TokenType.Function)
			return 3;
		
		if (tokenType != TokenType.Operateur)
			return -1;

		switch (value) {
		case "+":
		case "-":
			return 1;
		case "*":
		case "/":
			return 2;
		default:
			return -1;
		}
	}

	public Token(String value, Board board) {
		this.board = board;
		this.value = value;
		this.tokenType = TokenType.None;
		try {
			extractToken();
		} catch (InvalidAttributeValueException e) {
			e.printStackTrace();
		}
	}
	
	public Token(Integer value) {
		this.value = value.toString();
		this.tokenType = TokenType.Number;
	}
	

	Pattern cellPattern = Pattern.compile("[a-zA-Z]+[1-9]+[0-9]*");
	Pattern operatorPattern = Pattern.compile("\\+|\\-|\\*|\\/");
	Pattern numberPattern = Pattern.compile("[0-9]+");
	Pattern functionPattern = Pattern.compile("^\\(.+\\)$");

	private void extractToken() throws InvalidAttributeValueException {
		
		if(this.tokenType == TokenType.None)
		{
			if(cellPattern.matcher(value).matches()) tokenType = TokenType.Cell;
			else if(numberPattern.matcher(value).matches()) tokenType = TokenType.Number;
			else if(operatorPattern.matcher(value).matches()) tokenType = TokenType.Operateur;
			else if(functionPattern.matcher(value).matches()) tokenType = TokenType.Function;
		}
		if(this.tokenType == TokenType.None) throw new InvalidAttributeValueException("value : " + value + " can't be matched with any type");
		
		if(this.tokenType == TokenType.Cell)
		{
			int letterCount = 0;
			for (int i = 0; i < this.value.length(); i++) {
				if(!Character.isDigit(this.value.charAt(i))) letterCount++;
				else break;
			}
			String colString = this.value.substring(0,letterCount);
			colString = colString.toLowerCase();
			Integer col = Integer.valueOf(colString.charAt(0));
			col = col - 96;
			
			Integer row = Integer.valueOf(this.value.substring(letterCount,this.value.length()));
			this.value = String.valueOf(board.getBoard()[row-1][col-1].getProcessedValue());
			this.tokenType = TokenType.Number;
		}
		
		if(this.tokenType == TokenType.Function)
		{
			value = value.substring(1, value.length()-1); //trimming the parenthesis
			try {
				Stack<Token> stack = CellManager.sliceValue(value);
				value = String.valueOf(CellManager.processTokenStack(stack));
				tokenType = TokenType.Number;
			} catch (InvalidAttributeValueException e) {
				e.printStackTrace();
			}
		}
		
		
	}

	public TokenType getTokenType() {
		return tokenType;
	}

	public void setTokenType(TokenType tokenType) {
		this.tokenType = tokenType;
	}

	public String getValue() {
		if(tokenType == TokenType.Cell)
		{
			//TODO : return the value of the corresponding cell 
			return "0"; 
		}
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}
